package android.os.mock;

import android.annotation.Nullable;
import android.annotation.SystemService;
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;

import java.util.Map;

/**
 * @hide
 */
@SystemService(Context.MOCK_SERVICE)
public class MockManager {
    public static final String TAG = "MockManager";

    private static MockManager sInstance;
    private final IMockManager mService;

    private MockManager(IMockManager mockManager) {
        mService = mockManager;
    }

    
    public static MockManager getInstance() {
        synchronized (MockManager.class) {
            if (sInstance == null) {
                try {
                    sInstance = new MockManager(IMockManager.Stub.asInterface(
                            ServiceManager.getServiceOrThrow(Context.MOCK_SERVICE)));
                } catch (ServiceManager.ServiceNotFoundException e) {
                    throw new IllegalStateException(e);
                }
            }
            return sInstance;
        }
    }

    /**
     * 改机总开关，是否模拟，0不模拟，非0模拟
     *
     * @return 0不模拟，非0模拟
     */
    public int getPsState() {
        if (mService == null) return 0;
        try {
            return mService.getPsState();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * 是否模拟，getPsState() && isPsUid(uid) 的封装
     *
     * @return true需要模拟，false不模拟
     */
    public boolean isPs(int uid) {
        if (mService == null) return false;
        try {
            return mService.isPs(uid);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * 根据调用方uid来判断是否需要对返回给调用方的数据进行模拟
     *
     * @param uid 调用方uid
     * @return 是否需要模拟
     */
    public boolean isPsUid(int uid) {
        if (mService == null) return false;
        try {
            return mService.isPsUid(uid);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * 根据key返回数据，可以是返回路径、json或具体数据，
     * 返回路径的情况下需要考虑调用方是否有权限，做好临时提权，否则可能读不到数据
     *
     * @param key 需要获取的值对应的key
     * @return 返回结果，路径，json或具体数据，调用方做相应的处理
     */
    public String getPsInfo(String key) {
        if (mService == null) return null;
        try {
            return mService.getPsInfo(key);
        } catch (RemoteException e) {
        }
        return null;
    }

    // add by yhy (start)
    public String getSettingsInfo() {
        try {
            return mService.getPsInfo(MockManager.KEY_SETTINGS);
        } catch (RemoteException e) {
            throw new RuntimeException(e);
        }
    }
    // add by yhy (end)

    /**
     * 设置静态数据
     *
     * @param data 路径
     * @param map 额外参数
     * @param listener 监听
     */
    public void setStaticEnv(String data, @Nullable Map<String, String> map, @Nullable MockListener listener) {
        try {
            if (mService == null) {
                if (listener != null) {
                    listener.onFailed(-1, "service is null");
                }
                return;
            }

            mService.setStaticEnv(data, map, new IMockListener.Stub() {

                @Override
                public void onSuccess() {
                    if (listener != null) {
                        listener.onSuccess();
                    }
                }

                @Override
                public void onFailed(int code, String msg) {
                    if (listener != null) {
                        listener.onFailed(code, msg);
                    }
                }
            });
        } catch (RemoteException e) {
        }
    }

    /**
     * 设置动态数据
     *
     * @param data 路径
     * @param map 额外参数
     * @param listener 监听
     */
    public void setDynamicEnv(String data, @Nullable Map<String, String> map, @Nullable MockListener listener) {
        try {
            if (mService == null) {
                if (listener != null) {
                    listener.onFailed(-1, "service is null");
                }
                return;
            }

            mService.setDynamicEnv(data, map, new IMockListener.Stub() {

                @Override
                public void onSuccess() {
                    if (listener != null) {
                        listener.onSuccess();
                    }
                }

                @Override
                public void onFailed(int code, String msg) {
                    if (listener != null) {
                        listener.onFailed(code, msg);
                    }
                }
            });
        } catch (RemoteException e) {
        }
    }

    // public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList() {
    //     if (mService == null) return Collections.emptyList();
    //     try {
    //         return mService.getInstalledAccessibilityServiceList();
    //     } catch (RemoteException e) {
    //         Log.e(TAG, e.getMessage());
    //     }
    //     return Collections.emptyList();
    // }

    // public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList() {
    //     if (mService == null) return Collections.emptyList();
    //     try {
    //         return mService.getEnabledAccessibilityServiceList();
    //     } catch (RemoteException e) {
    //         Log.e(TAG, e.getMessage());
    //     }
    //     return Collections.emptyList();
    // }

    // public MockMemoryInfo getMockMemoryInfo() {
    //     if (mService == null) return null;
    //     try {
    //         return mService.getMockMemoryInfo();
    //     } catch (RemoteException e) {
    //         Log.e(TAG, "getMockMemoryInfo: ", e);
    //     }

    //     return null;
    // }


    // public Map<String, MockStructStatVfs> getMockStructStatVfsMap() {
    //     if (mService == null) return null;
    //     try {
    //         return mService.getMockStructStatVfsMap();
    //     } catch (RemoteException e) {
    //         Log.e(TAG, "getMockStructStatVfsMap: ", e);
    //     }

    //     return null;
    // }

    public interface MockListener {
        void onSuccess();
        void onFailed(int code, String msg);
    }

    // 记录下支持的key
    public static final String KEY_BATTERY = "battery";
    public static final String KEY_DRM = "drm";
    public static final String KEY_SIMCARDS = "simCards";
    public static final String KEY_BASE_STATION = "baseStation";
    public static final String KEY_NEIGHBORING_CELL_INFO = "neighboringCellInfo";
    public static final String KEY_WIFIS_INFO = "wifis";
    public static final String KEY_ANDROID_ID = "android_id";
    public static final String KEY_ACCESSIBILITY_SERVICE_LIST = "installedAccessibilityServiceList";
    public static final String KEY_FINGERPRINT = "fingerprint";
    public static final String KEY_NFC = "nfc";
    public static final String KEY_SENSORS = "sensors";
    public static final String KEY_INPUT_METHOD = "inputMethod";
    public static final String KEY_INPUT_DEVICE = "inputDevice";
    public static final String KEY_BLUETOOTH_NAME = "bluetooth_name";
    public static final String KEY_BLUETOOTH_MAC = "bluetooth_mac";
    public static final String KEY_NET_INTERFACE = "networkInterface";
    public static final String KEY_USER_AGENT = "useragent";
    public static final String KEY_WIFI_MAC = "wifiMac";
    public static final String KEY_DISPLAY = "displays";
    // add by yhy (start)
    public static final String KEY_SETTINGS = "settings";
    // add by yhy (end)
    // TODO: add more here
}
